<?php


namespace App\Commons\WechatOpenPlatform;


use App\Commons\WechatOpenPlatform\Exceptions\WechatOpenPlatformException;
use Illuminate\Support\Facades\Log;

class WechatOpenPlatformTool {
    /**
     * 一般正确请求 errcode 值 {errcode: 0, errmsg: "ok"}
     */
    const SUCCESS_RESPONSE_ERROR_CODE = 0;
    
    /**
     * 示例列表
     * @var array
     */
    private static $_instanceList = [];
    
    /**
     * 默认使用示例键名
     */
    const DEFAULT_INSTANCE_KEY = 'default';
    
    /**
     * 微信配置获取选中，对应 wechat.open_platform.下的某一个配置
     */
    const OPEN_PLATFORM_CONFIG_DEFAULT_SELECT = 'default';
    
    /**
     * 第三方平台应用对象
     * @var \EasyWeChat\OpenPlatform\Application
     */
    private $_openPlatformApp;
    
    /**
     * EasyWechatOpenPlatformTool constructor.
     *
     * @param null|string $configSelect
     * @param null|array  $config
     */
    public function __construct($configSelect = self::OPEN_PLATFORM_CONFIG_DEFAULT_SELECT, $config = null) {
        $openPlatformApp = \EasyWeChat\Factory::openPlatform($config ?: self::getOpenPlatformConfig($configSelect));
    
        //缓存设置
        if (config('wechat.defaults.use_laravel_cache')) {
            $laravelCache             = app('cache')->driver(env('WECHAT_OPEN_PLATFORM_CACHE_STORE'));
            $openPlatformApp['cache'] = new \Overtrue\LaravelWeChat\CacheBridge($laravelCache);
        }
    
        $this->_openPlatformApp = $openPlatformApp;
    }
    
    /**
     * 获取第三方开发平台示例
     * @return \EasyWeChat\OpenPlatform\Application
     */
    public function getOpenPlatformApp() {
        return $this->_openPlatformApp;
    }
    
    /**
     * 设置第三方开发平台示例
     *
     * @param \EasyWeChat\OpenPlatform\Application $openPlatformApp
     *
     * @return mixed
     */
    public function setOpenPlatformApp($openPlatformApp) {
        return $this->_openPlatformApp = $openPlatformApp;
    }
    
    /**
     * 获取微信第三方开发平台配置信息
     * @return \Illuminate\Config\Repository|mixed
     */
    public static function getOpenPlatformConfig($select = null) {
        return array_merge(config('wechat.defaults'),config('wechat.open_platform.' . ($select ?: self::OPEN_PLATFORM_CONFIG_DEFAULT_SELECT)));
    }
    
    /**
     * @param null $select
     *
     * @return array
     */
    public static function getOpenPlatformConfigWechatMiniProgramCommonExtJson($select = null) {
        return self::getOpenPlatformConfig($select)['wechat_mini_program_common']['ext_json'] ?? [];
    }
    
    /**
     * @param null $select
     *
     * @return array
     */
    public static function getOpenPlatformConfigWechatMiniProgramCommonServerDomain($select = null) {
        return self::getOpenPlatformConfig($select)['wechat_mini_program_common']['server_domain'] ?? [];
    }
    
    /**
     * @param null $select
     *
     * @return array
     */
    public static function getOpenPlatformConfigWechatMiniProgramCommonSetWebViewDomain($select = null) {
        return self::getOpenPlatformConfig($select)['wechat_mini_program_common']['webviewdomain'] ?? [];
    }
    
    /**
     * 获取指定工具类示例
     *
     * @param string $configSelect
     * @param null   $config
     *
     * @return WechatOpenPlatformTool
     */
    public static function getInstance(
        $configSelect = self::OPEN_PLATFORM_CONFIG_DEFAULT_SELECT,
        $config = null,
        $instanceKey = self::DEFAULT_INSTANCE_KEY,
        $isRefresh = false
    ) {
        if (!isset(self::$_instanceList[$instanceKey]) || $isRefresh) {
            self::$_instanceList[$instanceKey] = new self($configSelect, $config);
        }
        
        return self::$_instanceList[$instanceKey];
    }
    
    /**
     * 获取草稿列表
     *
     * @param bool $isRefresh
     * @param null $config
     *
     * @return mixed
     */
    public function getDraftsList() {
        return $this->getOpenPlatformApp()->code_template->getDrafts();
    }
    
    /**
     * 获取模板列表
     *
     * @param bool $isRefresh
     * @param null $config
     *
     * @return mixed
     */
    public function getTemplateList() {
        return $this->getOpenPlatformApp()->code_template->list();
    }
    
    /**
     * 将草稿添加到模板中
     *
     * @param int  $draftId
     * @param bool $isRefresh
     * @param null $config
     *
     * @return mixed
     */
    public function createTemplateCreateFromDraft(int $draftId) {
        return $this->getOpenPlatformApp()->code_template->createFromDraft($draftId);
    }
    
    /**
     * 删除小程序魔板
     *
     * @param      $templateId
     * @param bool $isRefresh
     * @param null $config
     *
     * @return mixed
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     */
    public function deleteTemplate($templateId) {
        return $this->getOpenPlatformApp()->code_template->delete($templateId);
    }
    
    /**
     * 获取授权链接
     *
     * @param       $callbackUrl
     * @param bool  $isMobil
     * @param array $optional
     * @param bool  $isRefresh
     * @param null  $config
     *
     * @return string
     */
    public function getComponentLoginPageUrl($callbackUrl, $isMobil = false, $optional = []) {
        $app = $this->getOpenPlatformApp();
        if ($isMobil) {
            return $app->getMobilePreAuthorizationUrl($callbackUrl, $optional);
        } else {
            return $app->getPreAuthorizationUrl($callbackUrl, $optional);
        }
    }
    
    /**
     * 获取小程序操作实例
     *
     * @param string                                                    $appId
     * @param string                                                    $refreshToken
     * @param \App\Models\App\AppProject                                $projectEl
     * @param null                                                      $accessToken
     * @param null|\EasyWeChat\OpenPlatform\Authorizer\Auth\AccessToken $openPlatformApp
     *
     * @return WechatOpenPlatformMiniProgramTool
     */
    public function getMiniProgramTool(string $appId, string $refreshToken, $projectEl = null, $accessToken = null, $openPlatformApp = null) {
        return new WechatOpenPlatformMiniProgramTool($openPlatformApp ?: $this->getOpenPlatformApp(), $appId, $refreshToken, $projectEl, $accessToken);
    }
    
    /**
     * 授权信息获取
     *
     * @param $authCode
     */
    public function handleAuthorize($authCode) {
        return $this->getOpenPlatformApp()->handleAuthorize($authCode);
    }
    
    /**
     * 获取授权方的帐号基本信息
     *
     * @param $appId
     */
    public function getAuthorizer($appId) {
        return $this->getOpenPlatformApp()->getAuthorizer($appId);
    }
    
    /**
     * 求情检测
     * 一般请求成功返回为 {errcode: 0, errmsg: "ok"}
     *
     * @param $requestName
     * @param $responseInfo
     * @param $extErrorDealFn
     * @param $extSuccessFn
     *
     * @return mixed
     * @throws \Exception
     */
    public static function checkWxResponseContent($requestName, $responseInfo, $extErrorDealFn = null, $extSuccessFn = null) {
        if (env('APP_ENV') !== 'production') {
            Log::info("发起微信 [ {$requestName} ] 请求,请求返回:");
            Log::info($responseInfo);
        }
        
        if (isset($responseInfo['errcode']) && $responseInfo['errcode'] == self::SUCCESS_RESPONSE_ERROR_CODE) {
            
            if (is_callable($extSuccessFn)) {
                return call_user_func_array($extSuccessFn, [$responseInfo]);
            }
            
            return $responseInfo;
        } else {
            Log::error("微信 [ {$requestName} ] 请求出错,请求返回异常:");
            Log::error($responseInfo);
            
            if (is_callable($extErrorDealFn)) {
                return call_user_func_array($extErrorDealFn, [$responseInfo]);
            }
            
            throw new WechatOpenPlatformException(1200001);
        }
    }
}